package model

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"gorm.io/gorm"
	"jsjb/tools"
	"strconv"
	"strings"

	"jsjb/connect"
	"jsjb/tools/aes"
	"jsjb/tools/random"
	"time"
)

var (
	ns   []OrgCate
	o    *OrgCate
	aoas []AuthOrgAccess
	agas []AuthGroupAccess
	aoa  AuthOrgAccess
	aga  AuthGroupAccess
	//ag *AuthGroup
)

type SearchAdmin struct {
	PageNo   int16  `json:"pageNo"form:"pageNo"`
	PageSize int16  `json:"pageSize"form:"pageSize"`
	Orgid    string `json:"orgId"form:"orgId"`
	GroupId  string `json:"groupId"form:"groupId"`
	Username string `json:"username"form:"username"`
	Telphone string `json:"telphone"form:"telphone"`
}
type Admin struct {
	Del           int8   `json:"del"form:"del"`
	Isleader      int8   `json:"isLeader"form:"isLeader"`
	Isprimary     int8   `json:"isPrimary"form:"isPrimary"`
	ID            int32  `json:"id"form:"id"`
	Createtime    int64  `json:"createTime"form:"createTime"`
	Updatetime    int64  `json:"updateTime"form:"updateTime"`
	Groupid       string `json:"groupid"form:"groupid"`
	Orgid         string `json:"orgid"form:"orgid"`
	Username      string `json:"username"form:"username"`
	Realname      string `json:"realName"form:"realName"`
	Password      string `json:"password"form:"password"`
	Telphone      string `json:"telphone"form:"telphone"`
	Salt          string `json:"salt"form:"salt"`
	Orgname       string `json:"orgName"form:"orgName"`
	Groupname     string `json:"groupName"form:"groupName"`
	Status        string `json:"status"form:"status"`
	Face          string `json:"face"form:"face"`
	Openid        string `json:"openid"form:"openid"`
	ElecSignature string `json:"elecSignature"form:"elecSignature"`
}

func (Admin) TableName() string {
	return "admin"
}
func QueryAdmins(s SearchAdmin) (admins []Admin, err error) {
	pageSize := s.PageSize
	pageNo := s.PageNo
	offset := (pageNo - 1) * pageSize
	var sql bytes.Buffer
	sql.WriteString("SELECT id, username, realname, password, salt, openid, face, telphone, GROUP_CONCAT( DISTINCT ooo.name SEPARATOR ',' ) AS orgname, GROUP_CONCAT( DISTINCT ooo.org_id SEPARATOR ',' ) AS orgid, GROUP_CONCAT( DISTINCT ggg.name SEPARATOR ',' ) AS groupname, GROUP_CONCAT( DISTINCT ggg.group_id SEPARATOR ',' ) AS groupid FROM admin  LEFT JOIN (SELECT aoa.adminid, oc.id AS org_id, oc.NAME FROM auth_org_access aoa LEFT JOIN org_cate oc ON aoa.orgid = oc.id ) ooo ON ooo.adminid = admin.id LEFT JOIN (SELECT aga.uid, ag.id AS group_id, ag.NAME FROM auth_group_access aga LEFT JOIN auth_group ag ON aga.group_id = ag.id ) ggg ON ggg.uid = admin.id ")
	sql.WriteString("WHERE 1=1 ")
	if s.Username != "" {
		sql.WriteString("AND username = '")
		sql.WriteString(s.Username)
		sql.WriteString("'")
	}
	if s.Telphone != "" {
		sql.WriteString("AND telphone = '")
		sql.WriteString(s.Telphone)
		sql.WriteString("'")
	}
	if s.GroupId != "" {
		sql.WriteString("AND FIND_IN_SET(ggg.group_id, '")
		sql.WriteString(s.GroupId)
		sql.WriteString("')")
	}
	if s.Orgid != "" {
		sql.WriteString("AND FIND_IN_SET(ooo.org_id, '")
		sql.WriteString(s.Orgid)
		sql.WriteString("')")
	}
	sql.WriteString("GROUP BY id LIMIT ?,?")
	connect.DB.Debug().Raw(sql.String(), offset, pageSize).Scan(&admins)
	return
}
func SetAdmin(admin *Admin) (id int64, err error) {
	if result := connect.DB.Omit("Groupid,Groupname").Create(admin); result.Error != nil {
		return 0, result.Error
	} else {
		id = result.RowsAffected
	}
	return
}
func UpdateAdmin(admin *Admin) (err error) {
	result := connect.DB.Model(admin).Select("*").Omit("Groupid").Updates(admin)
	err = result.Error
	return
}
func DeleteAdmins(admins []int32) (err error) {
	result := connect.DB.Where("id IN ?", admins).Delete(&Admin{})
	err = result.Error
	if err != nil {
		return
	}
	err = BatchDeleteAuthGroupAccess(admins)
	err = BatchDeleteAuthOrgAccess(admins)
	return
}
func (a *Admin) AfterDelete(tx *gorm.DB) (err error) {
	return
}
func (a *Admin) BeforeUpdate(tx *gorm.DB) (err error) {
	return
}
func (a *Admin) AfterUpdate(tx *gorm.DB) (err error) {
	//更新完组admin,然后删除对应adminId的auth_org_access 和auth_group_access
	//,然后新增
	DeleteAuthOrgAccess(a.ID)
	if strings.Contains(a.Orgid, ",") {
		sl := tools.StringToSliceInt32(a.Orgid)
		for _, v := range sl {
			aoa.Orgid = v
			aoa.Adminid = a.ID
			aoas = append(aoas, aoa)
		}
		err = BatchCreateAuthOrgAccess(aoas)
	} else {
		t, _ := strconv.Atoi(a.Orgid)
		aoa.Adminid = a.ID
		aoa.Orgid = int32(t)
		err = CreateAuthOrgAccess(aoa)
	}
	DeleteAuthGroupAccess(a.ID)
	if strings.Contains(a.Groupid, ",") {
		sl := tools.StringToSliceInt32(a.Groupid)
		for _, v := range sl {
			aga.GroupId = strconv.Itoa(int(v))
			aga.Uid = a.ID
			agas = append(agas, aga)
		}
		err = BatchCreateAuthGroupAccess(agas)
	} else {
		aga.Uid = a.ID
		aga.GroupId = a.Groupid
		CreateAuthGroupAccess(aga)
	}
	return
}
func (a *Admin) BeforeSave(db *gorm.DB) (err error) {

	if strings.Contains(a.Orgid, ",") {
		sl := tools.StringToSliceInt32(a.Orgid)
		ns, err = SelectOrgCate(sl)
		if err != nil {
			return
		}
		var sName []string
		for _, v := range ns {
			sName = append(sName, v.Name)
		}
		a.Orgname = strings.Join(sName, ",")
	} else {
		t, _ := strconv.Atoi(a.Orgid)
		o, err = FindOrgCate(int32(t))
		if err != nil {
			return
		}
		a.Orgname = o.Name
	}
	a.Salt = random.New("allNum", 6).Build()
	a.Password = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%x%s", md5.Sum([]byte(a.Password)), a.Salt))))
	a.Telphone = aes.Encrypt(a.Telphone)
	a.Createtime = time.Now().Unix()
	a.Updatetime = time.Now().Unix()
	a.Status = "normal"
	return
}
func (a *Admin) AfterCreate(db *gorm.DB) (err error) {
	if strings.Contains(a.Orgid, ",") {
		sl := tools.StringToSliceInt32(a.Orgid)
		for _, v := range sl {
			aoa.Orgid = v
			aoa.Adminid = a.ID
			aoas = append(aoas, aoa)
		}
		err = BatchCreateAuthOrgAccess(aoas)
	} else {
		t, _ := strconv.Atoi(a.Orgid)
		aoa.Adminid = a.ID
		aoa.Orgid = int32(t)
		CreateAuthOrgAccess(aoa)
	}
	if strings.Contains(a.Groupid, ",") {
		sl := tools.StringToSliceInt32(a.Groupid)
		for _, v := range sl {
			aga.GroupId = strconv.Itoa(int(v))
			aga.Uid = a.ID
			agas = append(agas, aga)
		}
		err = BatchCreateAuthGroupAccess(agas)
	} else {
		aga.Uid = a.ID
		aga.GroupId = a.Groupid
		CreateAuthGroupAccess(aga)
	}
	return
}
